package com.yuehuanghun.mybatismilu.test.controller;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.github.pagehelper.PageHelper;
import com.yuehuanghun.mybatis.milu.criteria.Predicate;
import com.yuehuanghun.mybatis.milu.criteria.Predicates;
import com.yuehuanghun.mybatis.milu.tool.Assert;
import com.yuehuanghun.mybatismilu.test.domain.entity.Student;
import com.yuehuanghun.mybatismilu.test.domain.mapper.StudentMapper;
import com.yuehuanghun.mybatismilu.test.service.StudentService;

@RestController
@RequestMapping("/student")
public class Studentcontroller {
	@Autowired
	private StudentService studentService;
	@Autowired
	private SqlSessionFactory sqlSessionFactory;

	@GetMapping("/{id}")
	public Student getById(@PathVariable Long id) {
		return studentService.getById(id).orElse(null);
	}
	
	@GetMapping("/list")
	public List<Student> list(Student param){
		PageHelper.startPage(1, 10);
		return studentService.getByCriteria(p -> p.gt("id", param.getId()));
	}
	
	@PostMapping
	public void save(@RequestBody Student student) {
		studentService.add(student);
	}
	
	private AtomicInteger counter = new AtomicInteger();
	private Random random = new Random();
	
	@PostMapping("/add")
	public void save() {
		Student student = new Student();
		student.setName("李" + counter.incrementAndGet());
		student.setAge(random.nextInt(100));
		student.setIsDeleted(Boolean.FALSE);
		student.setClassId(1L);
		studentService.add(student);
	}
	
	@PostMapping("/batch")
	@Transactional
	public void batchAdd() {
		long beginTime = System.currentTimeMillis();
		List<Student> list = new ArrayList<>(50);
		Student student;
		for(int i = 0; i < 500; i ++) {
			student = new Student();
			student.setAge(9);
			student.setClassId(1L);
			student.setName(randomName());
			list.add(student);
		}
		
		studentService.batchAdd(list);
		System.out.println("batchAdd耗时：" + (System.currentTimeMillis() - beginTime));
	}
	
	@PostMapping("/batchSave")
	@Transactional
	public void batchSave() {
		long beginTime = System.currentTimeMillis();
		List<Student> list = new ArrayList<>(500);
		Student student;
		for(int i = 0; i < 500; i ++) {
			student = new Student();
			student.setAge(9);
			student.setClassId(1L);
			student.setName(randomName());
			list.add(student);
		}
		
		studentService.batchSave(list);
		System.out.println("batchSave耗时：" + (System.currentTimeMillis() - beginTime));
	}
	
	@PostMapping("/batchSave2")
	public void batchSave2() {
		long beginTime = System.currentTimeMillis();
		List<Student> list = new ArrayList<>(500);
		Student student;
		for(int i = 0; i < 500; i ++) {
			student = new Student();
			student.setAge(9);
			student.setClassId(1L);
			student.setName(randomName());
			list.add(student);
		}
		
		studentService.batchSave(list);
		System.out.println("batchSave2耗时：" + (System.currentTimeMillis() - beginTime));
	}
	
	@PostMapping("/batchSave3")
	@Transactional
	public void batchSave3() {
		long beginTime = System.currentTimeMillis();
		SqlSession batchSqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH, false);
		StudentMapper mapper = batchSqlSession.getMapper(StudentMapper.class);
		Student student;
		for(int i = 0; i < 500; i ++) {
			student = new Student();
			student.setAge(9);
			student.setClassId(1L);
			student.setName(randomName());
			mapper.insert(student);
		}
		
		batchSqlSession.flushStatements();
		
		System.out.println("batchSave3耗时：" + (System.currentTimeMillis() - beginTime));
	}

	@PostMapping("/batchForEach")
	@Transactional
	public void batchForEach() {
		long beginTime = System.currentTimeMillis();
		Student student;
		for(int i = 0; i < 500; i ++) {
			student = new Student();
			student.setAge(9);
			student.setClassId(1L);
			student.setName(randomName());
			studentService.add(student);
		}
		
		System.out.println("batchForEach耗时：" + (System.currentTimeMillis() - beginTime));
	}
	
	private static String randomName() {
		return new String(new char[] {getRandomChar(), getRandomChar()});
	}
	
	private static char getRandomChar() {
        return (char) (0x4e00 + (int) (Math.random() * (0x9fa5 - 0x4e00 + 1)));
    }
	
	@GetMapping("findByCriteria")
	public void findByCriteria() {
		List<Student> list = studentService.getByCriteria(p -> p.eq("id", 1L));
		List<Student> list2 = studentService.getByCriteria(p -> p.eq("id", 1L));
		Assert.isTrue(list.equals(list2), "不一致");
	}

	@GetMapping("findByCriteriaUnion")
	public void findByCriteriaUnion() {
		Predicate predicate1 = Predicates.predicate();
		predicate1.eq("id", 1);
		Predicate predicate2 = Predicates.predicate();
		predicate2.eq("id", 2);
		
		List<Student> list = studentService.getByCriteriaUnion(predicate1, predicate2);
		
		Predicate predicate3 = Predicates.predicate();
		predicate3.eq("id", 1);
		Predicate predicate4 = Predicates.predicate();
		predicate4.eq("id", 2);
		
		List<Student> list2 = studentService.getByCriteriaUnion(predicate3, predicate4);
		Assert.isTrue(list.equals(list2), "不一致");
	}
}
